package org.hishenframework.web.validate.tag;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import org.hishenframework.web.validate.jqvalidate.JqueryValidateRule;
import org.hishenframework.web.validate.jqvalidate.Jsr2JqValidate;
import org.hishenframework.web.validate.jqvalidate.Jsr2JqValidatorCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* JavaJsr303转换JqueryValidator验证标记
* @author didi
*
*/
public class HishenValidateTag extends TagSupport {

	private static final long serialVersionUID = 1L;

	private Logger logger = LoggerFactory.getLogger(HishenValidateTag.class);
	
	private String className;

	@Override
	public int doStartTag() throws JspException {
		
		ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(pageContext.getServletContext());
		Jsr2JqValidatorCollection validatorCollection = (Jsr2JqValidatorCollection) applicationContext.getBean("jsr2JqValidatorCollection");
		if (validatorCollection == null) {
			logger.warn("Skip validator tag output. Because cannot found class jsr2JqValidatorCollection instance in Spring ApplicationContext!");
			return SKIP_BODY;
		}
		try {
			ArrayList<Field> fields = new ArrayList<Field>();
			Class<?> clazz = Class.forName(className);
			Class<?> tempClazz = clazz;
			//获取包括继承的所有属性
			do {
				for (Field field : tempClazz.getDeclaredFields()) {
					if (!fieldContains(fields, field)) {
						fields.add(field);
					}
				}
				tempClazz = tempClazz.getSuperclass();
			} while (!tempClazz.equals(Object.class));
			
			StringBuilder rulesBuilder = new StringBuilder("rules:{");
			StringBuilder messagesBuilder = new StringBuilder("messages:{");
			
			for (Field field : fields) {
				rulesBuilder.append(field.getName()).append(": {");
				messagesBuilder.append(field.getName()).append(": {");
				//是否有验证器
				boolean hasValidator = false;
				//是否有自定义验证信息
				boolean hasMessage = false;
				for (Annotation annotation : field.getAnnotations()) {
					Jsr2JqValidate java2JqValidator = validatorCollection.get(annotation.annotationType());
					if (java2JqValidator != null) {
						JqueryValidateRule rule = java2JqValidator.toJqueryValidatorRule(annotation);
						//添加过滤规则
						rulesBuilder.append(rule.getType()).append(":").append(rule.getValue()).append(",");
						//添加规则错误提示信息
						if (rule.getMessage().length() > 0) {
							java2JqValidator.beforeBuildScript(annotation, rule);
							messagesBuilder.append(rule.getType()).append(":\"").append(rule.getMessage()).append("\",");
							hasMessage = true;
						}
						hasValidator = true;
					}
				}
				//有规则则减去最后一个规则的逗号
				if (hasValidator)
					rulesBuilder.delete(rulesBuilder.length() - 1, rulesBuilder.length());
				//删除最后一个自定义信息的逗号
				if (hasMessage) {
					messagesBuilder.delete(messagesBuilder.length() - 1, messagesBuilder.length());
				}
				rulesBuilder.append("},");
				messagesBuilder.append("},");
			}
			rulesBuilder.delete(rulesBuilder.length() - 1, rulesBuilder.length());
			rulesBuilder.append("}");
			messagesBuilder.delete(messagesBuilder.length() - 1, messagesBuilder.length());
			messagesBuilder.append("}");
			
			//拼接HTML和JS代码
			StringBuilder htmlBulider = new StringBuilder();
			htmlBulider.append("<script id=\"hsvalidator\" type=\"text/javascript\">");
			htmlBulider.append("$(function(){");
			htmlBulider.append("$(\"#hsvalidator\").parents(\"form\").validate({");
			htmlBulider.append(rulesBuilder).append(",").append(messagesBuilder);
			htmlBulider.append("});");
			htmlBulider.append("});");
			htmlBulider.append("</script>");
			
			//输出拼接后的HTML和JS代码
			JspWriter out = pageContext.getOut();
			out.write(htmlBulider.toString());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		return SKIP_BODY;
	}

	/**
	 * 属性是否存在
	 * @param fieldList
	 * @param field
	 * @return
	 */
	private boolean fieldContains(List<Field> fieldList, Field field) {
		for (Field field2 : fieldList) {
			if (field2.getName().equals(field.getName())) {
				return true;
			}
		}
		return false;
	}
	
	//set
	
	public void setClassName(String className) {
		this.className = className;
	}
	

}